
#include "sc_gui.h"
#include "sc_transform.h"

#define    Q15   (1<<15)

#define GET_PIXEL(dst,Src,  srcx,  srcy,offs) (srcx >= 0 && srcx < Src->w && srcy >= 0 && srcy < Src->h) ? Src->buf[offs] : dst;

static inline void Bilinear_Interpolate(const SC_tile *Src, int32_t srcx, int32_t srcy,uint16_t *dst)
{

    uint8_t fx = (srcx ) >> 7;// 取余alpha
    uint8_t fy = (srcy ) >> 7;
    // 计算整数部分，定位到像素位置
    int32_t x = (srcx) >> 15;
    int32_t y = (srcy) >> 15;
    uint16_t p00,p01,p10,p11;
    int32_t offs= y*Src->w+x;
    if(x>0&&x<Src->w-1&&y>0&&y<Src->h-1)
    {
        p00 = Src->buf[offs];
        p10 = Src->buf[offs+1];
        p01 = Src->buf[offs+Src->w];
        p11 = Src->buf[offs+Src->w+1];
    }
    else
    {
        uint16_t cdst=*dst;
        p00 = GET_PIXEL(cdst,Src, x, y, offs);           // 左上角像素
        p10 = GET_PIXEL(cdst,Src, x+1,y, offs+1);        // 右上角像素
        p01 = GET_PIXEL(cdst,Src, x, y+1,offs+Src->w);   // 左下角像素
        p11 = GET_PIXEL(cdst,Src, x+1,y+1,offs+Src->w+1);// 右下角像素
    }
    // 在X方向进行权重插值
    uint16_t py0 = alphaBlend(p00, p10, 255 - fx);  // 左上和右上的插值
    uint16_t py1 = alphaBlend(p01, p11, 255 - fx);  // 左下和右下的插值
    // 在Y方向进行权重插值，返回最终结果
    *dst= alphaBlend(py0, py1, 255-fy);

}
////DMA画水平线,mirror镜像
//void _draw_line_x(int xs,int ys,uint16_t *src,int len,int mirror)
//{
//    if(ys<0||ys>= LCD_SCREEN_HEIGHT) return;         //y边界限定
//    int st= SC_MAX(xs,0);                             //xs边界限定
//    int end=SC_MIN(xs+len, LCD_SCREEN_WIDTH);         //xe边界限定
//    if(mirror>=0)
//    {
//        gui->dma_prt=src+st-xs;
//        gui->dma_i=end-st;
//        gui->Refresh(st,ys,gui->dma_i,1,gui->dma_prt);
//        return;
//    }
//    src+=len-1-(st-xs);        //src 偏移
//    for(xs=st; xs<end; xs++)
//    {
//        gui->dma_prt[gui->dma_i++]=*src;
//        src+=mirror;
//    }
//    gui->Refresh(st,ys,gui->dma_i,1,gui->dma_prt);
//}
//
//
////DMA画垂直线,mirror镜像
//void _draw_line_y(int xs,int ys,uint16_t *src,int len,int mirror)
//{
//    if(xs<0||xs>=LCD_SCREEN_WIDTH) return;   //x边界限定
//    int st= SC_MAX(ys,0);                     //ys边界限定
//    int end=SC_MIN(ys+len, LCD_SCREEN_HEIGHT);//ye边界限定
//    if(mirror>=0)
//    {
//        gui->dma_prt=src+st-ys;
//        gui->dma_i=end-st;
//        gui->Refresh(xs,st,1,gui->dma_i,gui->dma_prt);
//        return;
//    }
//    src+=len-1- (st-ys);            //src 偏移
//    for(ys=st; ys<end; ys++)
//    {
//        gui->dma_prt[gui->dma_i++]=*src;
//        src+=mirror;
//    }
//    gui->Refresh(xs,st,1,gui->dma_i,gui->dma_prt);
//}

//scaleX,scaleY放大256
void SC_transform(SC_tile *dest,const SC_tile *Src,Transform *p, int32_t Angle,uint16_t scaleX, uint16_t scaleY)
{
    int32_t rotatedX,rotatedY;
    int32_t Ax_16,Ay_16,Bx_16,By_16; //共用变量
    int32_t sinA = -sc_sin(Angle);   //符号控制正反转
    int32_t cosA =  sc_cos(Angle);

    int16_t max_dest_x =0;
    int16_t max_dest_y =0;
    int16_t min_dest_x = LCD_SCREEN_WIDTH;
    int16_t min_dest_y = LCD_SCREEN_HEIGHT;
    // 正映射缩放系数乘法
    Ax_16 = (cosA * scaleX )/256;  //cosAX
    Ay_16 = (sinA * scaleY )/256;  //sinAX
    Bx_16 = (sinA * scaleX )/256;  //sinAY
    By_16 = (cosA * scaleY )/256;  //cosAY
    // 定义源图像的四个角点
    int32_t corners[4][2] =
    {
        {0, 0},                  // 左上角
        {Src->w, 0},             // 右上角
        {0, Src->h},            // 左下角
        {Src->w, Src->h}       // 右下角
    };
    for (int i = 0; i < 4; ++i)
    {
        // 将每个角点平移到新的旋转中心坐标系
        int32_t translatedX = corners[i][0] - p->center_x;
        int32_t translatedY = corners[i][1] - p->center_y;
        // 正映射旋转并缩放返回坐标
        rotatedX  = ( translatedX * Ax_16 + translatedY * Bx_16) + p->move_x*Q15;
        rotatedY  = (-translatedX * Ay_16 + translatedY * By_16) + p->move_y*Q15;
        // 更新边界框
        min_dest_x = SC_MIN(min_dest_x, rotatedX/Q15-p->stup);
        max_dest_x = SC_MAX(max_dest_x, rotatedX/Q15+p->stup);
        min_dest_y = SC_MIN(min_dest_y, rotatedY/Q15-p->stup);
        max_dest_y = SC_MAX(max_dest_y, rotatedY/Q15+p->stup);
    }

    SC_ARER intersection;
    if(!SC_pfb_intersection(dest,&intersection,min_dest_x,min_dest_y,max_dest_x,max_dest_y))
    {
        // printf("is ret\r\n");
        return ;
    }
    //--------------------------------------------------
    // 反映射缩放系数是除
    Ax_16 = (cosA * 256/scaleX);  //cosAX
    Ay_16 = (sinA * 256/scaleX);  //sinAX
    Bx_16 = (sinA * 256/scaleY);  //sinAY
    By_16 = (cosA * 256/scaleY);  //cosAY
    int x,y;
    for ( y = intersection.ys; y <= intersection.ye; y++)
    {

        int32_t Cx_16 =  Bx_16 * (y-p->move_y)- p->center_x*Q15;
        int32_t Cy_16 =  By_16 * (y-p->move_y)+ p->center_y*Q15;
        int dest_offs=(y-dest->ys) * dest->w -dest->xs;
        for ( x = intersection.xs; x <= intersection.xe; x++)
        {
//        rotatedX =  Ax_16*(x-p->move_x) - Cx_16+p->center_x*Q15;  // 原公式
//        rotatedY =  Ay_16*(x-p->move_x) + Cy_16+p->center_x*Q15;  // 原公式
            rotatedX =  Ax_16*(x-p->move_x) - Cx_16;
            rotatedY =  Ay_16*(x-p->move_x) + Cy_16;
            // 转换到源图像坐标
            int32_t srcIntX = (int32_t)(rotatedX/Q15);
            int32_t srcIntY = (int32_t)(rotatedY/Q15);
            // 确保源坐标在有效范围内
            if (srcIntX >=0 && srcIntX < Src->w && srcIntY>=0 && srcIntY < Src->h)
            {
                Bilinear_Interpolate(Src,rotatedX,rotatedY,&dest->buf[dest_offs+x]); //插值
            }
            else
            {
                //dest->buf[dest_offs+x]=0;
            }
        }
    }

}

